package com.yvan.leto.server.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yvan.YvanUtil;
import com.yvan.leto.ResourceFoundException;
import com.yvan.leto.server.dao.ProjectPersistent;
import com.yvan.leto.server.domain.Project;
import com.yvan.leto.server.domain.ProjectFileContent;
import com.yvan.leto.server.domain.Segment;
import com.yvan.leto.server.service.ReleaseService;
import com.yvan.leto.server.utils.HttpJsonPayloadParser;
import com.yvan.leto.server.utils.HttpUtil;
import com.yvan.platform.ResultModel;
import lombok.val;
import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@RestController
public class ProjectController {

    @Autowired
    private ProjectPersistent projectPersistent;

    @Autowired
    private ReleaseService releaseService;

    @Autowired
    private ConfigFileController configFileController;

    @GetMapping("/projects")
    public ModelAndView projects() {
        ResultModel model = new ResultModel();
        final String env = HttpUtil.getEnv();

        val projects = projectPersistent.projectFindAll();
        List<Map<String, Object>> list = Lists.newArrayList();
        val projectSummaryMap = releaseService.selectProjectSummary(env, projects);
        for (String p : projects) {
            Map<String, Object> map = Maps.newLinkedHashMap();
            map.put("name", p);
            if (projectSummaryMap.containsKey(p)) {
                map.put("publish_time", projectSummaryMap.get(p).get("create_at"));
                map.put("rev_id", projectSummaryMap.get(p).get("rev_id"));
            } else {
                map.put("publish_time", "");
                map.put("rev_id", "");
            }
            list.add(map);
        }

        model.put("env", env);
        model.put("data", YvanUtil.toJsonPretty(list));
        return new ModelAndView("/projects.ftl", model);
    }

    @GetMapping("/project/{project}/struct")
    public ModelAndView projectAddNew(@PathVariable("project") String projectName) {
        ResultModel model = new ResultModel();

        ProjectFileContent contentJson = new ProjectFileContent();
        Project project;
        try {
            project = projectPersistent.projectFindByName(projectName);
            model.put("title", "修改项目 " + project.getName());
            contentJson.setAdd(false);

        } catch (ResourceFoundException e) {
            project = projectPersistent.newProject(projectName);
            model.set("title", "添加项目");
            contentJson.setAdd(true);
        }
        contentJson.setName(projectName);
        contentJson.setContent(projectPersistent.projectToJson(project));

        model.put("data", project);
        model.put("contentJson", YvanUtil.toJson(contentJson));
        return new ModelAndView("/project_struct.ftl", model);
    }

    @GetMapping("/project/{project}/segments")
    public ModelAndView projectSegments(@PathVariable("project") String projectName) {
        ResultModel model = new ResultModel();
        val project = projectPersistent.projectFindByName(projectName);

        //计算段落当前是否被发布
        for (Segment segment : project.getSegments()) {
            segment.setExists(releaseService.existsResult(HttpUtil.getEnv(), projectName, segment.getName()));
        }

        model.put("data", project);
        model.put("env", HttpUtil.getEnv());

        return new ModelAndView("/project_segments.ftl", model);
    }

    @GetMapping("/project/{project}/perm")
    public ModelAndView projectPerm(@PathVariable("project") String projectName) {
        ResultModel model = new ResultModel();
        val project = projectPersistent.projectFindByName(projectName);
        model.put("data", project);
        return new ModelAndView("/project_perm.ftl", model);
    }

    @GetMapping("/project/{project}/instance")
    public ModelAndView projectInstance(@PathVariable("project") String projectName) {
        ResultModel model = new ResultModel();
        val project = projectPersistent.projectFindByName(projectName);
        model.put("data", project);
        return new ModelAndView("/project_instance.ftl", model);
    }

    @GetMapping("/project/{project}/cf_view")
    public ModelAndView projectCfView(@PathVariable("project") String projectName,
                                      @RequestParam("full_name") String fullName) {
        ResultModel model = configFileController.fillModel(fullName);
        return new ModelAndView("/cf_view.ftl", model);
    }

    @GetMapping("/project/{project}/cf_edit")
    public ModelAndView projectCfEdit(@PathVariable("project") String projectName,
                                      @RequestParam("full_name") String fullName) {
        ResultModel model = configFileController.fillModel(fullName);
        return new ModelAndView("/cf_edit.ftl", model);
    }

    @GetMapping("/project/{project}/release")
    public ModelAndView projectRelease(@PathVariable("project") String projectName) {
        ResultModel model = new ResultModel();
        val project = projectPersistent.projectFindByName(projectName);
        model.put("data", project);
        return new ModelAndView("/project_release.ftl", model);
    }

    @GetMapping("/projects/verify_name")
    public Object verifyProjectName(@RequestParam("project") String projectName) {
        String msg = projectPersistent.verifyName(projectName);
        if (!StringUtils.isEmpty(msg)) {
            return ResultModel.newFail(msg);
        }
        return ResultModel.newSuccess();
    }

    @PostMapping("/project/{project}/struct")
    public Object projectEditPost(@PathVariable("project") String projectName,
                                  HttpServletRequest request) throws IOException {
        HttpJsonPayloadParser parser = new HttpJsonPayloadParser(request);
        ProjectFileContent param = parser.getJsonWapper().asObject(ProjectFileContent.class);
        try {
            projectPersistent.saveProject(param);
        } catch (Exception e) {
            return ResultModel.newFail(e.getMessage());
        }
        return ResultModel.newSuccess().putMsg("保存成功!");
    }

    @DeleteMapping("/project/{project}")
    public Object projectDeletePost(@PathVariable("project") String projectName) throws IOException {
        if (projectPersistent.deleteProject(projectName)) {
            return ResultModel.newSuccess().putMsg("删除成功!");
        }
        return ResultModel.newFail("删除失败");
    }

    @GetMapping("/project/{project}/{segment}/preview")
    public Object projectPreview(@PathVariable("project") String projectName,
                                 @PathVariable("segment") String segmentName,
                                 HttpServletRequest request) {
        throw new NotImplementedException();
    }

    @GetMapping("/project/{project}/{segment}/diff")
    public Object projectDiff(@PathVariable("project") String projectName,
                              @PathVariable("segment") String segmentName,
                              HttpServletRequest request) {
        throw new NotImplementedException();
    }

    @GetMapping("/project/{project}/{segment}/raw")
    public Object projectRaw(@PathVariable("project") String projectName,
                             @PathVariable("segment") String segmentName,
                             HttpServletRequest request) {
        throw new NotImplementedException();
    }
}
